package com.share.example.stock.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.share.common.common.Page;
import com.share.common.utils.DateUtil;
import com.share.common.utils.DecimalUtil;
import com.share.common.utils.ObjUtil;
import com.share.common.utils.ThreadUtil;
import com.share.example.stock.enums.StrategyEnum;
import com.share.example.stock.mapper.StockDayPriceMapper;
import com.share.example.stock.mapper.StrategyMapper;
import com.share.example.stock.model.db.StockBaseInfo;
import com.share.example.stock.model.db.StockDayPrice;
import com.share.example.stock.model.db.StrategyResult;
import com.share.example.stock.model.vo.*;
import com.share.example.stock.service.IStockBaseInfoService;
import com.share.example.stock.service.ITradeDateService;
import com.share.example.stock.service.SendMessage;
import com.share.example.stock.service.StrategyService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
public class StrategyServiceImpl implements StrategyService {

    @Resource
    private StrategyMapper strategyMapper;

    @Resource
    private StockDayPriceMapper stockDayPriceMapper;

    @Autowired
    private IStockBaseInfoService iStockBaseInfoService;

    @Autowired
    private ITradeDateService iTradeDateService;

    @Autowired
    private SendMessage sendMessage;

    public List<StockDayPrice> shizixin(String strDate) {
        QueryWrapper<StockDayPrice> wrapper = new QueryWrapper();
        //确定这一天的十
        wrapper.eq("date", strDate);
        wrapper.lt("ABS(co_o)", 0.001);
        wrapper.gt("hl_o", 0.03);

        //确定横线 的位置是否剧中
        wrapper.gt("cl_hl", 0.3);
        wrapper.gt("hc_hl", 0.3);

        wrapper.orderByDesc("cl_hl"); //下影线的高度排序

        List<StockDayPrice> dataList = stockDayPriceMapper.selectList(wrapper);

        if (!CollectionUtils.isEmpty(dataList)) {
            List<CodePirceO> msgList = new LinkedList<>();
            dataList.forEach(e -> {
                CodePirceO vo = new CodePirceO();
                vo.setPrice(e.getOpen());
                vo.setCode(e.getCode());
                msgList.add(vo);
            });

            //3.异步保存数据到db
            Date today = new Date();
            if (DateUtil.getDate(today).equals(strDate)) {
                ThreadUtil.execute(() -> saveOrUpdateOnedayStrategy(StrategyEnum.SHIZIXIN.getCode(), today, msgList));
            }

            //4.异步发送消息到邮件
            ThreadUtil.execute(() -> sendMessage.sendMSg2DingDingOrEmail(StrategyEnum.SHIZIXIN, msgList));
        }
        return dataList;
    }

    //更新当天的策略数据
    @Override
    public int saveOrUpdateOnedayStrategy(String strategyCode, Date oneDay, List<CodePirceO> list) {
        int reCount = 0;
        List<StrategyResult> insertList = new LinkedList<>();
        String strDate = DateUtil.getDate(oneDay);
        String strTime = DateUtil.getTime(oneDay);
        //查询某天的某个策略
        Map<String, StrategyCodeOneDay> codeMap = strategyMapper.mapByDateAndStrategy(strDate, strategyCode);
        for (CodePirceO item : list) {
            reCount++;
            String code = item.getCode();
            StrategyResult strategy = new StrategyResult();
            strategy.setCode(code);
            strategy.setDate(strDate);
            strategy.setStrategy(strategyCode);
            strategy.setTime(strTime);
            strategy.setLastPrice(item.getPrice());
            strategy.setLastRate(item.getOther());//比例的意思

            StrategyCodeOneDay oneDayCodes = codeMap.get(code);
            if (oneDayCodes == null) {//执行插入
                strategy.setPrice(item.getPrice());
                strategy.setStatus("1");
                StockBaseInfo stockCodeMap = iStockBaseInfoService.getStockCodeMap(code);
                if (stockCodeMap != null) {
                    strategy.setName(stockCodeMap.getName());
                    strategy.setIndustryName(stockCodeMap.getIndustryName());
                }
                insertList.add(strategy);
            } else {//执行更新
                strategyMapper.updateByCodeAndDate(strategy);
            }
        }

        //4.数据入库
        if (insertList.size() > 0) {
            log.info("批量插入size={}", insertList.size());
            int counti = strategyMapper.insertbatch(insertList);
        }

        return reCount;
    }

    //更新历史的策略数据
    @Override
    public int strategyMonitor(Date curDate, List<Code4Pirce> list) {
        String strDate = DateUtil.getDate(curDate);
        if (CollectionUtils.isEmpty(list)) {
            return 0;
        }

        //1.查询基础数据
        String strDate3 = iTradeDateService.getHistoryDay(strDate, -3);
        String strDate5 = iTradeDateService.getHistoryDay(strDate, -5);
        String strDate10 = iTradeDateService.getHistoryDay(strDate, -10);
        String strDate20 = iTradeDateService.getHistoryDay(strDate, -20);
        String strDate40 = iTradeDateService.getHistoryDay(strDate, -40);
        List<String> dateList = new LinkedList<>();
        dateList.add(strDate3);
        dateList.add(strDate5);
        dateList.add(strDate10);
        dateList.add(strDate20);
        dateList.add(strDate40);

        //code + "-" + strDate3
        Map<String, StrategyCodeDateVo> codeDateMap = strategyMapper.mapInDate(dateList);

        //逐条更新
        for (Code4Pirce code4Pirce : list) {
            String code = code4Pirce.getCode();
            updateOneIndere(code, strDate3, codeDateMap.get(code + "-" + strDate3), code4Pirce.getClose(), "3");
            updateOneIndere(code, strDate5, codeDateMap.get(code + "-" + strDate5), code4Pirce.getClose(), "5");
            updateOneIndere(code, strDate10, codeDateMap.get(code + "-" + strDate10), code4Pirce.getClose(), "10");
            updateOneIndere(code, strDate20, codeDateMap.get(code + "-" + strDate20), code4Pirce.getClose(), "20");
            updateOneIndere(code, strDate40, codeDateMap.get(code + "-" + strDate40), code4Pirce.getClose(), "40");
        }
        return 0;
    }


    private int updateOneIndere(String code, String strDate, StrategyCodeDateVo dbRecord, Double close, String flag) {
        int re = 0;
        if (dbRecord != null) {
            try {
                StrategyResult record = new StrategyResult();
                record.setCode(code);
                record.setDate(strDate);
                record.setLastPrice(close);
                record.setDnUpdateTime(new Date());
                Double aDouble = DecimalUtil.growthRatio(dbRecord.getPrice(), close, 4);
                if ("3".equals(flag)) {
                    record.setD3Rate(aDouble);
                } else if ("5".equals(flag)) {
                    record.setD5Rate(aDouble);
                } else if ("10".equals(flag)) {
                    record.setD10Rate(aDouble);
                } else if ("20".equals(flag)) {
                    record.setD20Rate(aDouble);
                } else if ("40".equals(flag)) {
                    record.setD40Rate(aDouble);
                }
                re = strategyMapper.updateByCodeAndDate(record);
            } catch (Exception e) {
                log.error("历史策略数据跟踪异常dbRecord={}", JSON.toJSON(dbRecord), e);
            }
        }
        return re;
    }

    @Override
    public int checkName() {
        int count = 0;
        QueryWrapper<StrategyResult> wrapper = new QueryWrapper();
        wrapper.select("DISTINCT code");
        wrapper.isNull("name").or();
        wrapper.isNull("industry_name");
        List<StrategyResult> dataList = strategyMapper.selectList(wrapper);
        for (StrategyResult item : dataList) {
            String code = item.getCode();
            StockBaseInfo stockCodeMap = iStockBaseInfoService.getStockCodeMap(code);
            if (stockCodeMap != null) {
                item.setName(stockCodeMap.getName());
                item.setIndustryName(stockCodeMap.getIndustryName());
                Map<String, Object> record = ObjUtil.toMap(item);
                if (record.size() > 2) {
                    strategyMapper.updateByCode(item);
                    count++;
                }
            }
        }
        return count;
    }

    @Override
    public Page pageList(StrategyPageReq req) {
        PageHelper.startPage(req.getPageNum(), req.getPageSize());
        QueryWrapper<StrategyResult> queryWrapper = new QueryWrapper();
        if (StringUtils.isNotBlank(req.getStrategy())) {
            queryWrapper.like("strategy", req.getStrategy());
        }

        if (StringUtils.isNotBlank(req.getName())) {
            queryWrapper.like("name", req.getName());
        }

        if (StringUtils.isNotBlank(req.getCode())) {
            queryWrapper.like("code", req.getCode());
        }
        if (StringUtils.isNotBlank(req.getCodes())) {
            List<String> list = Arrays.asList(req.getCodes().split(","));
            Set<String> tmpSet = list.stream().filter(e -> StringUtils.isNotBlank(e)).collect(Collectors.toSet());
            if (!CollectionUtils.isEmpty(tmpSet)) {
                queryWrapper.in("code", tmpSet);
            }
        }
        if (StringUtils.isNotBlank(req.getStartDate())) {
            queryWrapper.gt("date", req.getStartDate());
        }
        if (StringUtils.isNotBlank(req.getEndDate())) {
            //queryWrapper.lt（）——小于
            //queryWrapper.le（）——小于等于
            queryWrapper.lt("date", req.getEndDate());
        }
        queryWrapper.orderByDesc("id");
        List<StrategyResult> list = strategyMapper.selectList(queryWrapper);
        return new Page<>(list, new PageInfo<>(list).getTotal(), req);
    }
}
